/**
 * 可阻塞的任务队列，用于限定同时下载文件的队列数量
 */

const { log } = require('./util')

const TYPE_STACK = 'stack'       //堆栈类型：后进先出
const TYPE_QUEUE = 'queue'      //队列类型：先进先出

class TaskQueue {
    /**
     * 
     * @param {*} name 
     * @param {*} type 队列类型： stack | queue
     * @param {*} task 
     */
    constructor(name, task, type = TYPE_QUEUE) {
        this.name = name        //队列名称
        this.type = type        //队列类型
        this.task = task        //队列每个元素的操作函数，task函数必须返回 Promise 对象
        this.queue = []         //队列
        this.execCount = 0      //执行过的任务数量
        this.failCount = 0      //失败数量
        this.isRun = false      //是否正在执行
    }

    /**
     * 
     */
    take() {
        switch (this.type) {
            case TYPE_QUEUE: return this.queue.shift()
            case TYPE_STACK: return this.queue.pop()
        }
    }

    /**
     * 执行
     */
    async execute() {
        if (!this.isRun) {
            let args
            while (args = this.take()) {
                this.isRun = true
                try {
                    await this.task(args)
                } catch (e) {
                    log.error(`任务队列[${this.name}]出现异常：args=${args}, error=${e}`)
                    this.failCount++
                }
                this.execCount++
            }
            this.isRun = false
        }
    }

    /**
     * 
     * @param {添加元素} el 
     */
    push(el) {
        this.queue.push(el)
        this.execute()
    }

    /**
     * 队列长度
     */
    size() {
        return this.isRun ? this.queue.length + 1 : this.queue.length;
    }

    /**
     * 输出
     */
    toString() {
        return `队列名：${this.name}，类型：${this.type}，任务执行次数：${this.execCount}，队列长度：${this.queue.length}，失败次数：${this.failCount}`

    }
}


module.exports = {
    TaskQueue,
    type: {
        TYPE_STACK, TYPE_QUEUE
    }
}

